﻿// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Admin.NET.Core.Service;
using Microsoft.AspNetCore.Http;
using Admin.NET.Application.Entity;
using Admin.NET.Core.Enums;
using Furion.RemoteRequest;
using Flurl.Util;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Microsoft.AspNetCore.StaticFiles;
using Admin.NET.Application.Service.PayFess.Dto;
using StackExchange.Profiling.Storage;


namespace Admin.NET.Application;

/// <summary>
/// 缴费服务
/// </summary>
[ApiDescriptionSettings(ApplicationConst.GroupName, Order = 100)]
public class PayFessService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<PayFess> _payFessRep;
    private readonly SqlSugarRepository<House> _houseRep;
    public PayFessService(SqlSugarRepository<PayFess> payFessRep, SqlSugarRepository<House> houseRep)
    {
        _payFessRep = payFessRep;
        _houseRep = houseRep;
    }

    /// <summary>
    /// 分页查询缴费
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Page")]
    [DisplayName("分页查询缴费")]
    public async Task<SqlSugarPagedList<PayFessOutput>> Page(PagePayFessInput input)
    {
        input.SearchKey = input.SearchKey?.Trim();//去除两端空白字符
        var query = _payFessRep.AsQueryable()
        .LeftJoin<House>((a, b) => a.HouseId == b.Id).Where(a=>a.BillingStatus == PayBillingStatus.已支付) //左连接过滤了已支付的数据
        .WhereIF(!string.IsNullOrEmpty(input.SearchKey), a => a.SerialNumber.Contains(input.SearchKey) || a.BillNumber.Contains(input.SearchKey))
        .WhereIF(!string.IsNullOrWhiteSpace(input.BillNumber), a => a.BillNumber.Contains(input.BillNumber.Trim()))
        .WhereIF(input.ItemBil > 0, a => a.ItemBil == (PayItemBills)Enum.Parse(typeof(PayItemBills),input.ItemBil.ToString()))
        .WhereIF(input.PaymentTimeRange != null && input.PaymentTimeRange.Length == 2, a => a.PaymentTime >= input.PaymentTimeRange[0] && a.PaymentTime <= input.PaymentTimeRange[1])
        .WhereIF(input.Paymentmethod > 0, a => a.Paymentmethod == (PaymentMethods)input.Paymentmethod)
        .WhereIF(input.BillingStatus > 0, a => a.BillingStatus == (PayBillingStatus)input.BillingStatus)

        //将字段映射到PayFessOutput对象中
        .Select((a, b) => new PayFessOutput
        {
            Id = Convert.ToInt32(a.Id),
            SerialNumber = a.SerialNumber,
            BillNumber = a.BillNumber,
            ItemBil = a.ItemBil,
            PaidAmount = a.PaidAmount,
            PaymentTime = a.PaymentTime,
            Paymentmethod = a.Paymentmethod,
            Chargingcyclestart = a.Chargingcyclestart,
            ChargingcycleEnd = a.ChargingcycleEnd,
            AmountReceivable = a.AmountReceivable,
            ReceivableTime = a.ReceivableTime,
            BillingStatus = a.BillingStatus,
            HouseId = Convert.ToInt32(a.HouseId),
            houseName = b.houseName 
        })
        .ToPagedListAsync(input.Page, input.PageSize);//对查询结果进行分页

        return await query;

    }



    /// <summary>
    /// 增加缴费
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Add")]
    [DisplayName("增加缴费")]
    public async Task<long> Add(AddPayFessInput input)
    {
        var entity = input.Adapt<PayFess>();
        await _payFessRep.InsertAsync(entity);
        return entity.Id;
    }

    /// <summary>
    /// 删除缴费
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Delete")]
    [DisplayName("删除缴费")]
    public async Task Delete(DeletePayFessInput input)
    {
        var entity = await _payFessRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
        await _payFessRep.FakeDeleteAsync(entity);   //假删除
        //await _payFessRep.DeleteAsync(entity);   //真删除
    }

    /// <summary>
    /// 更新缴费
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Update")]
    [DisplayName("更新缴费")]
    public async Task Update(UpdatePayFessInput input)
    {
        var entity = input.Adapt<PayFess>();
        await _payFessRep.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
    }

    /// <summary>
    /// 获取缴费
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "Detail")]
    [DisplayName("获取缴费")]
    public async Task<PayFess> Detail([FromQuery] QueryByIdPayFessInput input)
    {
        return await _payFessRep.GetFirstAsync(u => u.Id == input.Id);
    }

    /// <summary>
    /// 获取缴费列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "List")]
    [DisplayName("获取缴费列表")]
    public async Task<List<PayFessOutput>> List([FromQuery] PagePayFessInput input)
    {
        return await _payFessRep.AsQueryable().Select<PayFessOutput>().ToListAsync();
    }
    /// <summary>
    /// 枚举下拉框
    /// </summary>
    /// <param name="sign"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "PayEnums")]
    [DisplayName("枚举下拉框")]
    public async Task<object> GetEnum(int sign)
    {
        //初始化变量
        object obj = null;
        //依次获取每个枚举的所有值
        switch (sign)
        {
            case 1:
                obj =  EnumHelper.GetEnums(typeof(PayItemBills));
                break;
            case 2:
                obj = EnumHelper.GetEnums(typeof(PaymentMethods));
                break;
            case 3:
                obj = EnumHelper.GetEnums(typeof(PayBillingStatus));
                break;
        }
        return  obj;
    }
    /// <summary>
    /// 导出缴费记录
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "Excel")]
    [DisplayName("导出缴费记录")]
    public async Task<ActionResult> GetExcel()
    {
        //使用XSSFWorkbook创建一个新的Excel工作簿，using确保工作薄结束时被正确关闭
        using (IWorkbook book = new XSSFWorkbook())
        {
            //在工作簿中创建一个新的工作表
            ISheet sheet = book.CreateSheet();
            //在工作表的第一行创建表头，并设置每个单元格的值。
            IRow headerRow = sheet.CreateRow(0);
            headerRow.CreateCell(0).SetCellValue("流水号");
            headerRow.CreateCell(1).SetCellValue("账单编号");
            headerRow.CreateCell(2).SetCellValue("所属房屋");
            headerRow.CreateCell(3).SetCellValue("账单类目");
            headerRow.CreateCell(4).SetCellValue("实收金额");
            headerRow.CreateCell(5).SetCellValue("缴费时间");
            headerRow.CreateCell(6).SetCellValue("支付方式");
            //从数据库中异步查询缴费记录，并将结果转换为 PayFessOutput 类型的列表
            var payFessList = await _payFessRep.AsQueryable().Select<PayFessOutput>().ToListAsync();
            //遍历缴费记录列表，为每条记录创建一行，并填充数据。然后行索引递增
            int rowIndex = 1;
            foreach (var item in payFessList)
            {
                IRow dataRow = sheet.CreateRow(rowIndex);
                dataRow.CreateCell(0).SetCellValue(item.SerialNumber);
                dataRow.CreateCell(1).SetCellValue(item.BillNumber);
                dataRow.CreateCell(2).SetCellValue(item.houseName);
                dataRow.CreateCell(3).SetCellValue(item.ItemBil.ToString());
                dataRow.CreateCell(4).SetCellValue(item.PaidAmount.ToString());
                dataRow.CreateCell(5).SetCellValue(item.PaymentTime.Value.ToString("yyyy-MM-dd HH:mm:ss"));
                dataRow.CreateCell(6).SetCellValue(item.BillingStatus.ToString());
                rowIndex++;
            }
            //使用 MemoryStream 将Excel工作簿写入内存
            using (MemoryStream ms = new MemoryStream())
            {
                book.Write(ms);
                byte[] bytes = ms.ToArray();
                //设置文件的内容类型为Excel文件，并生成一个包含当前时间的文件名
                string contentType = new FileExtensionContentTypeProvider().Mappings[".xlsx"];
                string fileName = "缴费信息表" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xlsx";

                // 使用 FileStreamResult 创建一个文件流结果，并将文件下载名称设置为生成的文件名a
                return new FileStreamResult(new MemoryStream(bytes), contentType)
                {
                    FileDownloadName = fileName
                };
            }
        }

    }
    /// <summary>
    /// 分页查询缴费订单
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "OrderPage")]
    [DisplayName("分页查询缴费订单")]
    public async Task<SqlSugarPagedList<PayFessOrderOutput>> OrderPage(PageOrderPayFessInput input)
    {
        input.SearchKey = input.SearchKey?.Trim();
        var query = _payFessRep.AsQueryable()
        .LeftJoin<House>((a, b) => a.HouseId == b.Id) // 确保是 IQueryable 类型
        .WhereIF(!string.IsNullOrEmpty(input.SearchKey), a => a.SerialNumber.Contains(input.SearchKey) || a.BillNumber.Contains(input.SearchKey))
        .WhereIF(!string.IsNullOrWhiteSpace(input.BillNumber), a => a.BillNumber.Contains(input.BillNumber.Trim()))
        .WhereIF(input.houseId>0, a => a.HouseId == input.houseId)
        .WhereIF(input.ItemBil > 0, a => a.ItemBil == (PayItemBills)Enum.Parse(typeof(PayItemBills), input.ItemBil.ToString()))
        .WhereIF(input.BillingStatus > 0, a => a.BillingStatus == (PayBillingStatus)input.BillingStatus)

        .Select((a, b) => new PayFessOrderOutput
        {
            Id = Convert.ToInt32(a.Id),
            SerialNumber = a.SerialNumber,
            BillNumber = a.BillNumber,
            ItemBil = a.ItemBil,
            PaidAmount = a.PaidAmount,
            PaymentTime = a.PaymentTime,
            Paymentmethod = a.Paymentmethod,
            Chargingcyclestart = a.Chargingcyclestart,
            ChargingcycleEnd = a.ChargingcycleEnd,
            AmountReceivable = a.AmountReceivable,
            ReceivableTime = a.ReceivableTime,
            BillingStatus = a.BillingStatus,
            houseId = Convert.ToInt32(a.HouseId),
            houseName = b.houseName
        })
        .ToPagedListAsync(input.Page, input.PageSize);

        return await query;

    }
    /// <summary>
    /// 获取缴费订单列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "OrderList")]
    [DisplayName("获取缴费订单列表")]
    public async Task<List<PayFessOrderOutput>> OrderList([FromQuery] PageOrderPayFessInput input)
    {
        return await _payFessRep.AsQueryable().Select<PayFessOrderOutput>().ToListAsync();
    }
    /// <summary>
    /// 房间列表下拉框
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "GetHouse")]
    [DisplayName("房间列表下拉框")]
    public async Task<List<House>> GetHouse()
    {
        //查找房间表
        var query = _houseRep.AsQueryable();

        return await query.Select<House>().ToListAsync();
    }
    /// <summary>
    /// 导出缴费订单信息
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "OrderExcel")]
    [DisplayName("导出缴费订单信息")]
    public async Task<ActionResult> OrderExcel()
    {
        using (IWorkbook book = new XSSFWorkbook())
        {
            ISheet sheet = book.CreateSheet();
            IRow headerRow = sheet.CreateRow(0);
            headerRow.CreateCell(0).SetCellValue("流水号");
            headerRow.CreateCell(1).SetCellValue("账单编号");
            headerRow.CreateCell(2).SetCellValue("所属房屋");
            headerRow.CreateCell(3).SetCellValue("账单类目");
            headerRow.CreateCell(4).SetCellValue("计费周期");
            headerRow.CreateCell(5).SetCellValue("计费周期(截至)");
            headerRow.CreateCell(6).SetCellValue("应收时间");
            headerRow.CreateCell(7).SetCellValue("应收金额");
            headerRow.CreateCell(8).SetCellValue("账单状态");

            var OrderPayFess = await _payFessRep.AsQueryable().Select<PayFessOrderOutput>().ToListAsync();
            int rowIndex = 1;
            foreach (var item in OrderPayFess)
            {
                IRow dataRow = sheet.CreateRow(rowIndex);
                dataRow.CreateCell(0).SetCellValue(item.Id);
                dataRow.CreateCell(1).SetCellValue(item.BillNumber);
                dataRow.CreateCell(2).SetCellValue(item.houseName);
                dataRow.CreateCell(3).SetCellValue(item.ItemBil.ToString());
                dataRow.CreateCell(4).SetCellValue(item.Chargingcyclestart.Value.ToString("yyyyMMdd"));
                dataRow.CreateCell(5).SetCellValue(item.ChargingcycleEnd.Value.ToString("yyyyMMdd"));
                dataRow.CreateCell(6).SetCellValue(item.ReceivableTime.Value.ToString("yyyyMMdd"));
                dataRow.CreateCell(7).SetCellValue(item.AmountReceivable.ToString());
                dataRow.CreateCell(8).SetCellValue(item.BillingStatus.ToString());
                rowIndex++;
            }

            using (MemoryStream ms = new MemoryStream())
            {
                book.Write(ms);
                byte[] bytes = ms.ToArray();
                string contentType = new FileExtensionContentTypeProvider().Mappings[".xlsx"];
                string fileName = "缴费信息订单表" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xlsx";

                // 使用 FileStreamResult 返回文件响应
                return new FileStreamResult(new MemoryStream(bytes), contentType)
                {
                    FileDownloadName = fileName
                };
            }
        }

    }
    /// <summary>
    /// 缴费订单详情
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "OrderPayById")]
    [DisplayName("缴费订单详情")]
    public async Task<List<PayFessOrderOutput>> OrderPayById([FromQuery]int pid) 
    {
        //左连接操作，将缴费订单信息与房屋信息进行关联，并通过房屋ID进行过滤
        //查询结果应该映射到 PayFessOrderOutput 类型的对象
        var query = _payFessRep.AsQueryable().LeftJoin<House>((a,b)=>a.HouseId == b.Id).Select<PayFessOrderOutput>().Where(a => a.Id == pid);

        //异步查询并将结果返回
        return await query.ToListAsync();
    }

}
